<?php
defined('JETEE_PATH') or exit();
/**
 * 错误输出
 * @param mixed $error 错误
 * @return void
 */
function halt($error) {
	$e = array();
	if (APP_DEBUG) {
		//调试模式下输出错误信息
		if (!is_array($error)) {
			$trace          = debug_backtrace();
			$e['message']   = $error;
			$e['file']      = $trace[0]['file'];
			$e['line']      = $trace[0]['line'];
			ob_start();
			debug_print_backtrace();
			$e['trace']     = ob_get_clean();
		} else {
			$e              = $error;
		}
	} else {
		//否则定向到错误页面
		$error_page         = C('ERROR_PAGE');
		if (!empty($error_page)) {
			redirect($error_page);
		} else {
			if (C('SHOW_ERROR_MSG'))
				$e['message'] = is_array($error) ? $error['message'] : $error;
			else
				$e['message'] = C('ERROR_MESSAGE');
		}
	}
	// 包含异常页面模板
	include C('TMPL_EXCEPTION_FILE');
	exit;
}

/**
 * 自定义异常处理
 * @param string $msg 异常消息
 * @param string $type 异常类型 默认为JeteeException
 * @param integer $code 异常代码 默认为0
 * @return void
 */
function throw_exception($msg, $type='JeteeException', $code=0) {
	if (class_exists($type, false))
		throw new $type($msg, $code);
	else
		halt($msg);        // 异常类型不存在则输出错误信息字串
}

/**
 * 浏览器友好的变量输出
 * @param mixed $var 变量
 * @param boolean $echo 是否输出 默认为True 如果为false 则返回输出字符串
 * @param string $label 标签 默认为空
 * @param boolean $strict 是否严谨 默认为true
 * @return void|string
 */
function dump($var, $echo=true, $label=null, $strict=true) {
	$label = ($label === null) ? '' : rtrim($label) . ' ';
	if (!$strict) {
		if (ini_get('html_errors')) {
			$output = print_r($var, true);
			$output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
		} else {
			$output = $label . print_r($var, true);
		}
	} else {
		ob_start();
		var_dump($var);
		$output = ob_get_clean();
		if (!extension_loaded('xdebug')) {
			$output = preg_replace('/\]\=\>\n(\s+)/m', '] => ', $output);
			$output = '<pre>' . $label . htmlspecialchars($output, ENT_QUOTES) . '</pre>';
		}
	}
	if ($echo) {
		echo($output);
		return null;
	}else
		return $output;
}

/**
 * 404处理 
 * 调试模式会抛异常 
 * 部署模式下面传入url参数可以指定跳转页面，否则发送404信息
 * @param string $msg 提示信息
 * @param string $url 跳转URL地址
 * @return void
 */
function _404($msg='',$url='') {
	APP_DEBUG && throw_exception($msg);
	if($msg && C('LOG_EXCEPTION_RECORD')) Log::write($msg);
	if(empty($url) && C('URL_404_REDIRECT')) {
		$url    =   C('URL_404_REDIRECT');
	}
	if($url) {
		redirect($url);
	}else{
		send_http_status(404);
		exit;
	}
}

/**
 * 设置当前页面的布局
 * @param string|false $layout 布局名称 为false的时候表示关闭布局
 * @return void
 */
function layout($layout) {
	if(false !== $layout) {
		// 开启布局
		C('LAYOUT_ON',true);
		if(is_string($layout)) { // 设置新的布局模板
			C('LAYOUT_NAME',$layout);
		}
	}else{// 临时关闭布局
		C('LAYOUT_ON',false);
	}
}

/**
 * URL组装 支持不同URL模式
 * @param string $url URL表达式，格式：'[分组/模块/操作#锚点@域名]?参数1=值1&参数2=值2...'
 * @param string|array $vars 传入的参数，支持数组和字符串
 * @param string $suffix 伪静态后缀，默认为true表示获取配置值
 * @param boolean $redirect 是否跳转，如果设置为true则表示跳转到该URL地址
 * @param boolean $domain 是否显示域名
 * @return string
 */
function U($url='',$vars='',$suffix=true,$redirect=false,$domain=false) {
	// 解析URL
	$info   =  parse_url($url);
	$url    =  !empty($info['path'])?$info['path']:ACTION_NAME;
	if(isset($info['fragment'])) { // 解析锚点
		$anchor =   $info['fragment'];
		if(false !== strpos($anchor,'?')) { // 解析参数
			list($anchor,$info['query']) = explode('?',$anchor,2);
		}        
		if(false !== strpos($anchor,'@')) { // 解析域名
			list($anchor,$host)    =   explode('@',$anchor, 2);
		}
	}elseif(false !== strpos($url,'@')) { // 解析域名
		list($url,$host)    =   explode('@',$info['path'], 2);
	}
	// 解析子域名
	if(isset($host)) {
		$domain = $host.(strpos($host,'.')?'':strstr($_SERVER['HTTP_HOST'],'.'));
	}elseif($domain===true){
		$domain = $_SERVER['HTTP_HOST'];
		if(C('APP_SUB_DOMAIN_DEPLOY') ) { // 开启子域名部署
			$domain = $domain=='localhost'?'localhost':'www'.strstr($_SERVER['HTTP_HOST'],'.');
			// '子域名'=>array('项目[/分组]');
			foreach (C('APP_SUB_DOMAIN_RULES') as $key => $rule) {
				if(false === strpos($key,'*') && 0=== strpos($url,$rule[0])) {
					$domain = $key.strstr($domain,'.'); // 生成对应子域名
					$url    =  substr_replace($url,'',0,strlen($rule[0]));
					break;
				}
			}
		}
	}

	// 解析参数
	if(is_string($vars)) { // aaa=1&bbb=2 转换成数组
		parse_str($vars,$vars);
	}elseif(!is_array($vars)){
		$vars = array();
	}
	if(isset($info['query'])) { // 解析地址里面参数 合并到vars
		parse_str($info['query'],$params);
		$vars = array_merge($params,$vars);
	}
	
	// URL组装
	$depr = C('URL_PATHINFO_DEPR');
	if($url) {
		if(0=== strpos($url,'/')) {// 定义路由
			$route      =   true;
			$url        =   substr($url,1);
			if('/' != $depr) {
				$url    =   str_replace('/',$depr,$url);
			}
		}else{
			if('/' != $depr) { // 安全替换
				$url    =   str_replace('/',$depr,$url);
			}
			// 解析分组、模块和操作
			$url        =   trim($url,$depr);
			$path       =   explode($depr,$url);
			$var        =   array();
			$var[C('VAR_ACTION')]       =   !empty($path)?array_pop($path):ACTION_NAME;
			$var[C('VAR_MODULE')]       =   !empty($path)?array_pop($path):MODULE_NAME;
			if(C('URL_CASE_INSENSITIVE')) {
				//$var[C('VAR_MODULE')]   =   parse_name($var[C('VAR_MODULE')]);
				$var[C('VAR_MODULE')]   =  strtolower($var[C('VAR_MODULE')]);
			}
			if(!C('APP_SUB_DOMAIN_DEPLOY') && C('APP_GROUP_LIST')) {
				if(!empty($path)) {
					$group                  =   array_pop($path);
					$var[C('VAR_GROUP')]    =   $group;
				}else{
					if(GROUP_NAME != C('DEFAULT_GROUP')) {
						$var[C('VAR_GROUP')]=   GROUP_NAME;
					}
				}
				if(C('URL_CASE_INSENSITIVE') && isset($var[C('VAR_GROUP')])) {
					$var[C('VAR_GROUP')]    =  strtolower($var[C('VAR_GROUP')]);
				}
			}
		}
	}

	if(isset($route)) {
		$url    =   __APP__.'/'.rtrim($url,$depr);
	}else{
		$url    =   __APP__.'/'.implode($depr,array_reverse($var));
	}
	if(!empty($vars)) { // 添加参数
		foreach ($vars as $var => $val){
			if('' !== trim($val))   $url .= $depr . $var . $depr . urlencode($val);
		}                
	}
	if($suffix) {
		$suffix   =  $suffix===true?C('URL_HTML_SUFFIX'):$suffix;
		if($pos = strpos($suffix, '|')){
			$suffix = substr($suffix, 0, $pos);
		}
		if($suffix && '/' != substr($url,-1)){
			$url  .=  '.'.ltrim($suffix,'.');
		}
	}
	if(isset($anchor)){
		$url  .= '#'.$anchor;
	}
	if($domain) {
		$url   =  (IS_SSL?'https://':'http://').$domain.$url;
	}
	if($redirect) // 直接跳转URL
		redirect($url);
	else
		return $url;
}

/**
 * 渲染输出Widget
 * @param string $name Widget名称
 * @param array $data 传入的参数
 * @param boolean $return 是否返回内容 
 * @param string $path Widget所在路径
 * @return void
 */
function W($name, $data=array(), $return=false,$path='') {
	$class      =   $name . 'Widget';
	$path       =   empty($path) ? LIB_PATH : $path;
	require_cache($path . 'Widget/' . $class . '.class.php');
	if (!class_exists($class))
		throw_exception(L('_CLASS_NOT_EXIST_') . ':' . $class);
	$widget     =   Jetee::instance($class);
	$content    =   $widget->render($data);
	if ($return)
		return $content;
	else
		echo $content;
}

/**
 * 过滤器方法 引用传值
 * @param string $name 过滤器名称
 * @param string $content 要过滤的内容
 * @return void
 */
function filter($name, &$content) {
	$class      =   $name . 'Filter';
	require_cache(LIB_PATH . 'Filter/' . $class . '.class.php');
	$filter     =   new $class();
	$content    =   $filter->run($content);
}



/**
 * URL重定向
 * @param string $url 重定向的URL地址
 * @param integer $time 重定向的等待时间（秒）
 * @param string $msg 重定向前的提示信息
 * @return void
 */
function redirect($url, $time=0, $msg='') {
	//多行URL地址支持
	$url        = str_replace(array("\n", "\r"), '', $url);
	if (empty($msg))
		$msg    = "系统将在{$time}秒之后自动跳转到{$url}！";
	if (!headers_sent()) {
		// redirect
		if (0 === $time) {
			header('Location: ' . $url);
		} else {
			header("refresh:{$time};url={$url}");
			echo($msg);
		}
		exit();
	} else {
		$str    = "<meta http-equiv='Refresh' content='{$time};URL={$url}'>";
		if ($time != 0)
			$str .= $msg;
		exit($str);
	}
}
function initCache($name='',$options=null){
	static $cache   =   '';
	if(is_array($name)) { // 缓存初始化
		$type       =   isset($name['type'])?$name['type']:'';
		$cache      =   Cache::getInstance($type,$name);
	}elseif(empty($cache)) { // 自动初始化
		if(is_array($options)){
			$type       =   isset($options['type'])?$options['type']:'';
			$cache      =   Cache::getInstance($type,$options);
		}else $cache      =   Cache::getInstance();
	}
	return $cache;
}
/**
 * 缓存管理  空闲状态  从初始化到获取值一般0.0015内
 * @param mixed $name 缓存名称，如果为数组表示进行缓存设置
 * @param mixed $value 缓存值
 * @param mixed $options 缓存参数  如果是数字为过期时间秒
 * @return mixed  取值不存在 返回false
 */
function S($name,$value='',$options=null){
	$cache=initCache($name,$options);
	if(''=== $value){//获取缓存
		return $cache->g($name);
	}elseif(is_null($value)) {//删除缓存
		return $cache->rm($name);
	}else {//缓存数据
		if(is_array($options)) {
			$expire     =   isset($options['expire'])?$options['expire']:NULL;
		}else{
			$expire     =   is_int($options)?$options:NULL;
		}
		return $cache->s($name, $value, $expire);
	}
}

/**
 * 缓存数组管理
 * @param mixed $name 缓存名称，如果为数组表示进行缓存设置
 * @param mixed $arr 键值对
 * @param mixed $options 缓存参数  如果是数字为过期时间秒
 * @return mixed
 */
function hm($name,$arr='',$options=null) {
	$cache=initCache($name,$options);
	if(''=== $arr){ // 获取缓存
		return $cache->hGetAll($name);
	}elseif(is_null($arr)) { // 删除缓存
		return $cache->rm($name);
	}else{ //缓存数据
		if(is_array($options)) {
			$expire     =   isset($options['expire'])?$options['expire']:NULL;
		}else{
			$expire     =   is_int($options)?$options:NULL;
		}
		return $cache->hmSet($name, $arr, $expire);
	}
}
/**
 * 缓存数组键值管理
 * @param mixed $name 缓存名称，如果为数组表示进行缓存设置
 * @param mixed $key 键
 * @param mixed $val 值
 * @param mixed $options 缓存参数  如果是数字为过期时间秒
 * @return mixed
 */
function h($name,$key,$val='',$options=null) {
	$cache=initCache($name,$options);
	if(''=== $val){// 获取缓存
		return $cache->hGet($name,$key);
	}elseif(is_null($val)) { // 删除缓存
		return $cache->rm($name);
	}else{//缓存数据
		if(is_array($options)) {
			$expire     =   isset($options['expire'])?$options['expire']:NULL;
		}else{
			$expire     =   is_int($options)?$options:NULL;
		}
		return $cache->hSet($name, $key, $val, $expire);
	}
}

/**
 * 快速文件数据读取和保存 针对简单类型数据 字符串、数组  消除opcache影响
 * @param string $name 缓存名称
 * @param mixed $value 缓存值
 * @param string $path 缓存路径
 * @return mixed
 */
function F($name, $value='', $path=DATA_PATH) {
	static $_cache  = array();
	$filename       = $path . $name . '.php';
	if ('' !== $value) {
		if (is_null($value)) {
			// 删除缓存
			return false !== strpos($name,'*')?array_map("unlink", glob($filename)):unlink($filename);
		} else {
			// 缓存数据
			$dir            =   dirname($filename);
			// 目录不存在则创建
			if (!is_dir($dir))
				mkdir($dir,0755,true);
			$_cache[$name]  =   $value;
			$return=file_put_contents($filename, strip_whitespace("<?php\treturn " . var_export($value, true) . ";?>"));
			if(OPCACHE_ENABLE)
				opcache_invalidate($filename);
			return $return;
		}
	}
	if (isset($_cache[$name]))
		return $_cache[$name];
	// 获取缓存数据
	if (is_file($filename)) {
		$value          =   include $filename;
		$_cache[$name]  =   $value;
	} else {
		$value          =   false;
	}
	return $value;
}
/**
 * 取得对象实例 支持调用类的静态方法
 * @param string $name 类名
 * @param string $method 方法名，如果为空则返回实例化对象
 * @param array $args 调用参数
 * @return object
 */
function get_instance_of($name, $method='', $args=array()) {
	static $_instance = array();
	$identify = empty($args) ? $name . $method : $name . $method . to_guid_string($args);
	if (!isset($_instance[$identify])) {
		if (class_exists($name)) {
			$o = new $name();
			if (method_exists($o, $method)) {
				if (!empty($args)) {
					$_instance[$identify] = call_user_func_array(array(&$o, $method), $args);
				} else {
					$_instance[$identify] = $o->$method();
				}
			}
			else
				$_instance[$identify] = $o;
		}
		else
			halt(L('_CLASS_NOT_EXIST_') . ':' . $name);
	}
	return $_instance[$identify];
}

/**
 * 根据PHP各种类型变量生成唯一标识号
 * @param mixed $mix 变量
 * @return string
 */
function to_guid_string($mix) {
	if (is_object($mix) && function_exists('spl_object_hash')) {
		return spl_object_hash($mix);
	} elseif (is_resource($mix)) {
		$mix = get_resource_type($mix) . strval($mix);
	} else {
		$mix = serialize($mix);
	}
	return md5($mix);
}

/**
 * XML编码
 * @param mixed $data 数据
 * @param string $root 根节点名
 * @param string $item 数字索引的子节点名
 * @param string $attr 根节点属性
 * @param string $id   数字索引子节点key转换的属性名
 * @param string $encoding 数据编码
 * @return string
 */
function xml_encode($data, $root='think', $item='item', $attr='', $id='id', $encoding='utf-8') {
	if(is_array($attr)){
		$_attr = array();
		foreach ($attr as $key => $value) {
			$_attr[] = "{$key}=\"{$value}\"";
		}
		$attr = implode(' ', $_attr);
	}
	$attr   = trim($attr);
	$attr   = empty($attr) ? '' : " {$attr}";
	$xml    = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
	$xml   .= "<{$root}{$attr}>";
	$xml   .= data_to_xml($data, $item, $id);
	$xml   .= "</{$root}>";
	return $xml;
}

/**
 * 数据XML编码
 * @param mixed  $data 数据
 * @param string $item 数字索引时的节点名称
 * @param string $id   数字索引key转换为的属性名
 * @return string
 */
function data_to_xml($data, $item='item', $id='id') {
	$xml = $attr = '';
	foreach ($data as $key => $val) {
		if(is_numeric($key)){
			$id && $attr = " {$id}=\"{$key}\"";
			$key  = $item;
		}
		$xml    .=  "<{$key}{$attr}>";
		$xml    .=  (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
		$xml    .=  "</{$key}>";
	}
	return $xml;
}

/**
 * session管理函数
 * @param string|array $name session名称 如果为数组则表示进行session设置
 * @param mixed $value session值
 * @return mixed
 */
function session($name,$value='') {
	$prefix   =  C('SESSION_PREFIX');
	if(is_array($name)) { // session初始化 在session_start 之前调用
		if(isset($name['prefix'])){
			C('SESSION_PREFIX',$name['prefix']);
			$prefix   =  $name['prefix'];
		}
		if(C('VAR_SESSION_ID') && isset($_REQUEST[C('VAR_SESSION_ID')])){
			session_id($_REQUEST[C('VAR_SESSION_ID')]);
		}elseif(isset($name['id'])) {
			session_id($name['id']);
		}
		ini_set('session.auto_start', 0);
		if(isset($name['expire']))			session_set_cookie_params($name['expire']);//ini_set('session.cookie_lifetime', $name['expire']); //session_id cookie过期时间
		if(isset($name['name']))            session_name($prefix.$name['name']);//cookie session_id
		if(isset($name['path']))            session_save_path($name['path']);
		if(isset($name['domain']))          ini_set('session.cookie_domain', $name['domain']);
		if(isset($name['expire']))          ini_set('session.gc_maxlifetime', $name['expire']);  //垃圾回收
		if(isset($name['use_trans_sid']))   ini_set('session.use_trans_sid', $name['use_trans_sid']?1:0);//0使用URL sid,1为cookie  
		if(isset($name['use_cookies']))     ini_set('session.use_cookies', $name['use_cookies']?1:0);//使用cookie传输sid
		if(isset($name['cache_limiter']))   session_cache_limiter($name['cache_limiter']);//  指定public浏览器端变成private  下面才生效为什么？   这两个是控制header  http头部
		if(isset($name['cache_expire']))   	session_cache_expire($name['cache_expire']);// 以分钟数指定缓冲的会话页面的存活期   是http头部expires 
		if(isset($name['type']))            C('SESSION_TYPE',$name['type']);
		if(C('SESSION_TYPE')) { // 读取session驱动
			$class      = 'Session'. ucwords(strtolower(C('SESSION_TYPE')));
			// 检查驱动类
			if(class_exists($class)) {
				$hander = new $class();
				$hander->execute();
			}else {
				// 类没有定义
				throw_exception(L('_CLASS_NOT_EXIST_').': ' . $class);
			}
		}
		// 启动session
		if(C('SESSION_AUTO_START'))  session_start();
		//header_remove('Expires');		header_remove('Pragma');
	}
	elseif('' === $value){ 
		if(0===strpos($name,'[')) { // session 操作
			if('[pause]'==$name){ // 暂停session
				session_write_close();
			}elseif('[start]'==$name){ // 启动session
				session_start();
			}elseif('[destroy]'==$name){ // 销毁session
				$_SESSION =  array();
				session_unset();
				session_destroy();
			}elseif('[regenerate]'==$name){ // 重新生成id
				session_regenerate_id();
			}
		}elseif(0===strpos($name,'?')){ // 检查session
			$name   =  substr($name,1);
			if(strpos($name,'.')){ // 支持数组
				list($name1,$name2) =   explode('.',$name);
				return $prefix?isset($_SESSION[$prefix][$name1][$name2]):isset($_SESSION[$name1][$name2]);
			}else{
				return $prefix?isset($_SESSION[$prefix][$name]):isset($_SESSION[$name]);
			}
		}elseif(is_null($name)){ // 清空session
			if($prefix) {
				unset($_SESSION[$prefix]);
			}else{
				$_SESSION = array();
			}
		}elseif($prefix){ // 获取session
			if(strpos($name,'.')){
				list($name1,$name2) =   explode('.',$name);
				return isset($_SESSION[$prefix][$name1][$name2])?$_SESSION[$prefix][$name1][$name2]:null;  
			}else{
				return isset($_SESSION[$prefix][$name])?$_SESSION[$prefix][$name]:null;                
			}            
		}else{
			if(strpos($name,'.')){
				list($name1,$name2) =   explode('.',$name);
				return isset($_SESSION[$name1][$name2])?$_SESSION[$name1][$name2]:null;  
			}else{
				return isset($_SESSION[$name])?$_SESSION[$name]:null;
			}            
		}
	}elseif(is_null($value)){ // 删除session
		if($prefix){
			unset($_SESSION[$prefix][$name]);
		}else{
			unset($_SESSION[$name]);
		}
	}else{ // 设置session
		if($prefix){
			if (!is_array($_SESSION[$prefix])) {
				$_SESSION[$prefix] = array();
			}
			if(strpos($name,'.')){
				list($name1,$name2) =   explode('.',$name);
				$_SESSION[$prefix][$name1][$name2]   =  $value;
			}else{
				$_SESSION[$prefix][$name]   =  $value;                
			}
		}else{
			if(strpos($name,'.')){
				list($name1,$name2) =   explode('.',$name);
				$_SESSION[$name1][$name2]   =  $value;
			}else{
				$_SESSION[$name]   =  $value;                
			}
		}
	}
}
/**
 * Cookie 设置、获取、删除
 * @param string $name cookie名称
 * @param mixed $value cookie值
 * @param mixed $options cookie参数
 * @return mixed
 */
function cookie($name, $value='', $option=null) {
	// 默认设置
	$config = array(
		'prefix'    =>  C('COOKIE_PREFIX'), // cookie 名称前缀
		'expire'    =>  C('COOKIE_EXPIRE'), // cookie 保存时间
		'path'      =>  C('COOKIE_PATH'), // cookie 保存路径
		'domain'    =>  C('COOKIE_DOMAIN'), // cookie 有效域名
		'secure'    =>  C('COOKIE_SECURE'), // cookie 有效域名
		'httponly'  =>  C('COOKIE_HTTPONLY'), // cookie 有效域名
	);
	// 参数设置(会覆盖黙认设置)
	if (!is_null($option)) {
		if (is_numeric($option))
			$option = array('expire' => $option);
		elseif (is_string($option))
			parse_str($option, $option);
		$config     = array_merge($config, array_change_key_case($option));
	}
	// 清除指定前缀的所有cookie
	if (is_null($name)) {
		if (empty($_COOKIE))
			return;
		// 要删除的cookie前缀，不指定则删除config设置的指定前缀
		$prefix = empty($value) ? $config['prefix'] : $value;
		if (!empty($prefix)) {// 如果前缀为空字符串将不作处理直接返回
			foreach ($_COOKIE as $key => $val) {
				if (0 === stripos($key, $prefix)) {
					setcookie($key, '', time() - 3600, $config['path'], $config['domain']);
					unset($_COOKIE[$key]);
				}
			}
		}
		return;
	}
	$name = $config['prefix'] . $name;
	if ('' === $value) {
		if(isset($_COOKIE[$name])){
			$value =    $_COOKIE[$name];
			if(0===strpos($value,'jetee:')){
				$value  =   substr($value,6);
				return array_map('urldecode',json_decode(MAGIC_QUOTES_GPC?stripslashes($value):$value,true));
			}else{
				return $value;
			}
		}else{
			return null;
		}
	} else {
		if (is_null($value)) {
			setcookie($name, '', time() - 3600, $config['path'], $config['domain']);
			unset($_COOKIE[$name]); // 删除指定cookie
		} else {
			// 设置cookie
			if(is_array($value)){
				$value  = 'jetee:'.json_encode(array_map('urlencode',$value));
			}
			$expire = !empty($config['expire']) ? time() + intval($config['expire']) : 0;
			setcookie($name, $value, $expire, $config['path'], $config['domain']);
			$_COOKIE[$name] = $value;
		}
	}
}

/**
 * 加载动态扩展文件
 * @return void
 */
function load_ext_file() {
	// 加载自定义外部文件
	if(C('LOAD_EXT_FILE')) {
		$files      =  explode(',',C('LOAD_EXT_FILE'));
		foreach ($files as $file){
			include COMMON_PATH.$file.'.php';
		}
	}
	// 加载自定义的动态配置文件
	if(C('LOAD_EXT_CONFIG')) {
		$configs =  explode(',',C('LOAD_EXT_CONFIG'));
		foreach ($configs as $config){
			C(include CONF_PATH.$config.'.php');
		}
	}
}

/**
 * 获取客户端IP地址
 * @param integer $type 返回类型 0 返回IP地址 1 返回IPV4地址数字
 * @return mixed
 */
function get_client_ip($type = 0) {
	$type       =  $type ? 1 : 0;
	static $ip  =   NULL;
	if ($ip !== NULL) return $ip[$type];
	if (isset($_SERVER['REMOTE_ADDR'])) {//不可伪装，但可能是代理ip
		$ip     =   $_SERVER['REMOTE_ADDR'];
	}
	elseif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//可以curl伪装
		$arr    =   explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);
		$pos    =   array_search('unknown',$arr);
		if(false !== $pos) unset($arr[$pos]);
		$ip     =   trim($arr[0]);
	}elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
		$ip     =   $_SERVER['HTTP_CLIENT_IP'];
	}
	// IP地址合法验证
	$long = sprintf("%u",ip2long($ip));
	$ip   = $long ? array($ip, $long) : array('0.0.0.0', 0);
	return $ip[$type];
}

/**
 * 发送HTTP状态
 * @param integer $code 状态码
 * @return void
 */
function send_http_status($code) {
	static $_status = array(
		// Informational 1xx
		100 => 'Continue',
		101 => 'Switching Protocols',
		// Success 2xx
		200 => 'OK',
		201 => 'Created',
		202 => 'Accepted',
		203 => 'Non-Authoritative Information',
		204 => 'No Content',
		205 => 'Reset Content',
		206 => 'Partial Content',
		// Redirection 3xx
		300 => 'Multiple Choices',
		301 => 'Moved Permanently',
		302 => 'Moved Temporarily ', // 1.1
		303 => 'See Other',
		304 => 'Not Modified',
		305 => 'Use Proxy',
		// 306 is deprecated but reserved
		307 => 'Temporary Redirect',
		// Client Error 4xx
		400 => 'Bad Request',
		401 => 'Unauthorized',
		402 => 'Payment Required',
		403 => 'Forbidden',
		404 => 'Not Found',
		405 => 'Method Not Allowed',
		406 => 'Not Acceptable',
		407 => 'Proxy Authentication Required',
		408 => 'Request Timeout',
		409 => 'Conflict',
		410 => 'Gone',
		411 => 'Length Required',
		412 => 'Precondition Failed',
		413 => 'Request Entity Too Large',
		414 => 'Request-URI Too Long',
		415 => 'Unsupported Media Type',
		416 => 'Requested Range Not Satisfiable',
		417 => 'Expectation Failed',
		// Server Error 5xx
		500 => 'Internal Server Error',
		501 => 'Not Implemented',
		502 => 'Bad Gateway',
		503 => 'Service Unavailable',
		504 => 'Gateway Timeout',
		505 => 'HTTP Version Not Supported',
		509 => 'Bandwidth Limit Exceeded'
	);
	if(isset($_status[$code])) {
		header('HTTP/1.1 '.$code.' '.$_status[$code]);
		// 确保FastCGI模式下正常
		header('Status:'.$code.' '.$_status[$code]);
	}
}

// 过滤表单中的表达式
function think_filter(&$value){
	// TODO 其他安全过滤

	// 过滤查询特殊字符
	if(preg_match('/^(EXP|NEQ|GT|EGT|LT|ELT|OR|LIKE|NOTLIKE|NOTBETWEEN|NOT BETWEEN|BETWEEN|NOTIN|NOT IN|IN)$/i',$value)){
		$value .= ' ';
	}
}

// 表单令牌验证
function check_token() {
	if(C('TOKEN_ON')){
		$name   = C('TOKEN_NAME');
		$cookie_value=cookie($name);
		if(!$cookie_value || !session('?'.$name)) { // 令牌数据无效
			return false;
		}

		// 令牌验证
		if($cookie_value && session($name)=== $cookie_value) { // 防止重复提交
			session($name,null); // 验证完成销毁session
			return true;
		}
		// 开启TOKEN重置
		if(C('TOKEN_RESET')) session($name,null);
		return false;
	}
	return true;
}

function buildToken(){
	if(C('TOKEN_ON')){
		$tokenName  = C('TOKEN_NAME');
		$tokenType  = C('TOKEN_TYPE');
		$cookie=cookie($tokenName);
		$session=session($tokenName);	
		if(!$cookie || !$session || $cookie != $session) {// 存在不重复生成session
			$tokenValue = $tokenType(microtime(TRUE));
			session($tokenName,$tokenValue);
			cookie($tokenName, $tokenValue);
		}else $tokenValue=session($tokenName);	
		return   $tokenValue;
	}
	return '';
}
